package com.quyuanfactory.xvaidedemo;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Color;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.SeekBar;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.quyuanfactory.xvaide.XVAide;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

public class MainActivity extends Activity {
    private static final String TAG = MainActivity.class.getSimpleName();

    private Context mContext;
    private boolean loadedXVAide = false;
    private boolean hasOverlayPermission = false;

    private C108Face51 face51;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
//        findViewById(R.id.butStart).setBackgroundColor(loadedXVAide ? 0xff008577 : Color.LTGRAY);

        //pose animation
        byte[] data = decodeAssetResData(getApplicationContext(), "AI.uface");
        face51      = new C108Face51(data);
        data        = null;
        ((SeekBar)findViewById(R.id.sliderPose)).setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                Log.d(TAG, "progress: "+progress);
                float[] d = face51.GetFaceDataByRatio(progress*0.01f);
                if(null == d){return;}
                XVAide.AnimatePose("Manual","Tou",d);
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) { }
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) { }
        });
    }

    @Override
    public void onDestroy() {
        face51.Destroy();
        xvStop();

        super.onDestroy();
    }

    //UI
    public void clickButGoto(View view) {
        startActivity(new Intent(this, SecondActivity.class));
    }
    public void clickButStart(View view) {
        if(!hasOverlayPermission){
            doCheckOverlayPermission(new CallBackOverlayPermission() {
                @Override
                public void onResult(boolean ret) {
                    hasOverlayPermission = ret;
                    if(!hasOverlayPermission){Toast.makeText(mContext, "请设置窗口浮动权限！", Toast.LENGTH_SHORT).show();}
                    XVAide.SetOverlayPermission(hasOverlayPermission);
                    xvStart();
                }
            });
            return;
        }
        xvStart();
    }

    public void clickButStop(View view) {
        xvStop();
    }

    public void clickButShowRect(View view){
        if(!loadedXVAide){return;}
        float[] rect = new float[]{0.79f, 0.79f, 0.2f, 0.2f};
        XVAide.ShowModelRect(rect);
        XVAide.ShowModel();

        Rect frame = new Rect();
        getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        float w = frame.width();
        float h = frame.height();

        float[] rt = XVAide.ModelRect();
        Log.d(TAG, "XVAide.ModelRect: "+rt[0]+" "+rt[1]+" "+rt[2]+" "+rt[3] + " Real Rect(x,y,w,h): "+(w*rt[0])+" "+(h*rt[1])+" "+(w*rt[2])+" "+(h*rt[3]));
    }

    public void clickButShowNodes(View view){
        if(!loadedXVAide){return;}
        //["toufa","Tou","Eye_R","Eye_L","xifu","body","Leg","Shoes5"]
        //show all nodes
        //[XVAide ShowModelNodes:null];
        //show Head
        //XVAide.ShowModelNodes(new String[]{"toufa", "Tou", "Eye_R", "Eye_L"});
        //show Head And Body
        XVAide.ShowModelNodes(new String[]{"toufa", "Tou", "Eye_R", "Eye_L", "xifu", "body"});
        XVAide.ShowModel();
    }

    //////////////////////////////////////////////////////////////////////////
    //SDK
    private void xvStart(){
        if(loadedXVAide || !hasOverlayPermission){return;}
        XVAide.Init(this,callBack);
    }

    private void xvStop(){
        XVAide.Destroy();
        loadedXVAide = false;
        findViewById(R.id.butStart).setBackgroundColor(loadedXVAide ? 0xff008577 : Color.LTGRAY);
    }

    //////////////////////////////////////////////////////////////////////////
    private class C108Face51 {
        public int iNumTotalFaceData;
        public float posTime;
        public float durTime;
        public boolean loop; //true

        public int Count;    //pose size

        public ArrayList faceData = new ArrayList<float[]>();

        public  C108Face51(byte[] data)
        {
            Count = 57;
            loop  = true;
            iNumTotalFaceData = 0;

            if(null == data){return;}

            String ai = new String(data);
            String[] p = ai.split(",");

            iNumTotalFaceData = p.length / Count;
            durTime = iNumTotalFaceData * 1.0f / 60.0f;
            posTime = 0.0f;

            for(int i=0; i<iNumTotalFaceData; ++i){
                float[] d = new float[Count];
                for(int k=0; k<Count; ++k){
                    d[k] = Float.parseFloat(p[i*Count+k]);
                }
                faceData.add(d);
            }
        }
        public void Destroy() {
            for(int i=0; i<iNumTotalFaceData; ++i){
                faceData.set(i, null);
            }
            faceData.clear();
            faceData = null;
        }

        private float Clamp(float val, float minval, float maxval) {
            return Math.max(Math.min(val, maxval), minval);
        }

        private float Mod(float pos, float dur) {
            return (float) (pos - Math.floor(pos / dur)*dur);
        }

        public float[] GetFaceDataByRatio(float ratio) {
            float timePos = durTime * ratio;
            if (timePos != posTime){
                posTime = timePos;
                if (loop){// Wrap
                    posTime = Mod(posTime, durTime);
                    if (posTime < 0) posTime += durTime;
                }else{// Clamp
                    posTime = Clamp(posTime, 0.0f, durTime);
                }
                float ra = posTime * 1.0f / durTime;
                int iIndexFrame = (int)Math.floor(ra * (iNumTotalFaceData-1));
                return (float[]) faceData.get(iIndexFrame);
            }
            return null;
        }
    }
    public static byte[] decodeAssetResData(android.content.Context context,String resName) {
        // on 1.6 later
        AssetManager assetManager = context.getAssets();
        InputStream is;
        try {
            is = assetManager.open(resName);
            java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();

            byte[] bufferByte = new byte[1024];
            int l;
            while ((l = is.read(bufferByte)) > -1) {
                bout.write(bufferByte, 0, l);
            }
            byte[] rBytes = bout.toByteArray();
            bout.close();
            is.close();
            return rBytes;

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    //////////////////////////////////////////////////////////////////////////
    //CHECK OVERLAY PERMISSION
    private static final int OVERLAY_PERMISSION_REQ_CODE = 2;
    private static interface CallBackOverlayPermission {
        public void onResult(boolean ret);
    }
    private CallBackOverlayPermission cbOverlayPermission;
    private void doCheckOverlayPermission(CallBackOverlayPermission cb){
        cbOverlayPermission = cb;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 7.0 以上需要引导用去设置开启窗口浮动权限
            if (!Settings.canDrawOverlays(mContext)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + this.getPackageName()));
                startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
            }else{
                if(null != cbOverlayPermission){cbOverlayPermission.onResult(true);}
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // 6.0 动态申请窗口浮动权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}, OVERLAY_PERMISSION_REQ_CODE);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode != OVERLAY_PERMISSION_REQ_CODE) {return;}

        boolean ret = Settings.canDrawOverlays(mContext);
        if(null != cbOverlayPermission){cbOverlayPermission.onResult(ret);}

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode != OVERLAY_PERMISSION_REQ_CODE){return;}

        boolean ret = (grantResults[0] == PackageManager.PERMISSION_GRANTED);
        if(null != cbOverlayPermission){cbOverlayPermission.onResult(ret);}
    }
    //////////////////////////////////////////////////////////////////////////

     XVAide.CallBack callBack = new XVAide.CallBack() {
        @Override
        public void aideLoaded(boolean ret) {
            Log.d(TAG, "aideLoaded: " + ret);

            //////////////

//            if(!loadedXVAide){return;}
            float[] rect = new float[]{0.79f, 0.79f, 0.2f, 0.2f};
            XVAide.ShowModelRect(rect);
            XVAide.ShowModel();

//            Rect frame = new Rect();
//            getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
//            float w = frame.width();
//            float h = frame.height();
//
//            float[] rt = XVAide.ModelRect();


            //////////////


            loadedXVAide = ret;

            findViewById(R.id.butStart).setBackgroundColor(loadedXVAide ? 0xff008577 : Color.LTGRAY);
        }

        @Override
        public void aideClicked(String name) {
            //{"Idle","Nod","SayNo","Happy","Unhappy","Walk","Run","Great","Rest","TurnAround","Think","SayHello","Point","LookUp","Bow"};
            Log.d(TAG, "aideClicked: "+name);
            if(name.equals("Tou")){
                XVAide.StopAnimatePose("Manual","Tou"); //stop pose animation, reset, not necessary!, for demo
                XVAide.Animate("Nod",20.0f);
            }else if(name.equals("qunzi")){
                XVAide.Animate("Great",20.0f);
            }else if(name.equals("Leg")){
                XVAide.Animate("Walk",20.0f);
            }
        }

        @Override
        public void aideDoubleClicked(String name) {
            Log.d(TAG, "aideDoubleClicked: "+name);
        }

        @Override
        public void animateFinished(String name) {
            Log.d(TAG, "animateFinished: "+name);
        }
    };
}